import React, { useRef, useState } from 'react';
import { Button, Input, InputAdornment, Space, Switch, Tree } from 'tdesign-react';
import type { TreeInstanceFunctions, TreeNodeModel, TreeProps } from 'tdesign-react';

const items = [
  {
    value: 'node1',
  },
  {
    value: 'node2',
    disabled: true,
  },
];

let index = 2;

export default () => {
  const treeRef = useRef<TreeInstanceFunctions<{ value: string; label?: string }>>(null);

  const [activeMultiple, setActiveMultiple] = useState(false);
  const [useActived, setUseActived] = useState(false);
  const [expandParent, setExpandParent] = useState(false);
  const [filterText, setFilterText] = useState('');
  const [activeIds, setActiveIds] = useState([]);
  const [checkStrictly, setCheckStrictly] = useState(false);

  const getLabelContent = (node: TreeNodeModel) => {
    const pathNodes = node.getPath();
    let label = pathNodes.map((itemNode) => itemNode.getIndex() + 1).join('.');
    label = `${label} | value: ${node.value}`;
    return label;
  };

  const getLabel: TreeProps['label'] = (node) => {
    const label = getLabelContent(node);
    const { data } = node;
    data.label = label;
    return label;
  };

  const handleInputChange = (value: string) => {
    setFilterText(value);
    console.info('on input:', value);
  };

  const filterByText: TreeProps['filter'] = (node) => {
    const label = node?.data?.label || '';
    const rs = (label as string).indexOf(filterText) >= 0;
    return rs;
  };

  const handleExpand: TreeProps['onExpand'] = (vals, state) => {
    console.info('on expand:', vals, state);
  };

  const handleChange: TreeProps['onChange'] = (vals, state) => {
    console.info('on change:', vals, state);
  };

  const handleActive: TreeProps['onActive'] = (vals, state) => {
    console.info('on active:', vals, state);
    setActiveIds(vals);
  };

  /* ======== 操作 api ======= */

  const setLabel = (value: string) => {
    const node = treeRef.current.getItem(value);
    const label = getLabelContent(node);
    const { data } = node;
    data.label = label;
  };

  const getActivedNodes = () => activeIds.map((id) => treeRef.current.getItem(id));

  const getInsertItem = () => {
    let item = null;
    index += 1;
    const value = `t${index}`;
    item = {
      value,
    };
    return item;
  };

  const append = (node?: TreeNodeModel) => {
    const item = getInsertItem();
    if (!item) return;
    if (!node) {
      treeRef.current.appendTo('', item);
    } else {
      treeRef.current.appendTo(node.value, item);
    }
    if (useActived) {
      if (activeMultiple) {
        setActiveIds((v) => [...v, item.value]);
      } else {
        setActiveIds([item.value]);
      }
    }
  };

  const insertBefore = (node: TreeNodeModel) => {
    const item = getInsertItem();
    if (item) {
      treeRef.current.insertBefore(node.value, item);
      setLabel(item.value);
    }
  };

  const insertAfter = (node: TreeNodeModel) => {
    const item = getInsertItem();
    if (item) {
      treeRef.current.insertAfter(node.value, item);
      setLabel(item.value);
    }
  };

  const canToggleDisable = (node: TreeNodeModel) => {
    const parent = node.getParent?.();
    const isCheckStrictly = false; // 默认关闭
    if (!isCheckStrictly && parent?.disabled) {
      return false; // 父节点被禁用时，子节点状态不支持手动改变
    }
    return true;
  };

  const toggleDisable = (node: TreeNodeModel) => {
    treeRef.current.setItem(node.value, {
      disabled: !node.disabled,
    });
    console.log(treeRef.current.getItems(node.value));
  };

  const remove = (node: TreeNodeModel) => {
    treeRef.current.remove(node.value);
  };

  const renderOperations2 = (node: TreeNodeModel) => (
    <>
      <Button style={{ marginLeft: '10px' }} size="small" variant="base" onClick={() => append(node)}>
        添加子节点
      </Button>
      <Button style={{ marginLeft: '10px' }} size="small" variant="outline" onClick={() => insertBefore(node)}>
        前插节点
      </Button>
      <Button style={{ marginLeft: '10px' }} size="small" variant="outline" onClick={() => insertAfter(node)}>
        后插节点
      </Button>
      <Button
        style={{ marginLeft: '10px' }}
        size="small"
        variant="base"
        theme={node.disabled ? 'success' : 'warning'}
        disabled={!canToggleDisable(node)}
        onClick={() => toggleDisable(node)}
      >
        {node.disabled ? 'enable' : 'disable'}
      </Button>
      <Button style={{ marginLeft: '10px' }} size="small" variant="base" theme="danger" onClick={() => remove(node)}>
        删除
      </Button>
    </>
  );

  /* ======== API ======= */
  const getItem = () => {
    const node = treeRef.current.getItem('node1');
    console.info('getItem:', node.value);
  };

  const getAllItems = () => {
    const nodes = treeRef.current.getItems();
    console.info(
      'getAllItems:',
      nodes.map((node) => node.value),
    );
  };

  const getActiveChildren = () => {
    console.log(activeIds);
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    const allChildren: Array<TreeNodeModel> = [];
    nodes.forEach((node) => {
      const child = node.getChildren(true);
      if (Array.isArray(child)) {
        allChildren.push(...child);
      }
    });
    console.info(
      'getActiveChildren:',
      allChildren.map((node) => node.value),
    );
  };

  const getAllActived = () => {
    console.info('getActived value:', activeIds.slice(0));
  };

  const getActiveChecked = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    const allCheckedNodes: Array<TreeNodeModel> = [];
    nodes.forEach((node) => {
      const nodeItems = treeRef.current.getItems(node.value);
      allCheckedNodes.push(...nodeItems.filter((item) => item.checked));
    });
    console.info(
      'getChecked:',
      allCheckedNodes.map((node) => node.value),
    );
  };

  const getActiveParent = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    const parents = nodes
      .map((node) => {
        const parent = treeRef.current.getParent(node.value);
        return parent;
      })
      .filter(Boolean);
    console.info(
      'getParent',
      parents.map((parent) => parent.value),
    );
  };

  const getActiveParents = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    const allParents: Array<TreeNodeModel> = [];
    nodes.forEach((node) => {
      const parents = treeRef.current.getParents(node.value);
      allParents.push(...parents);
    });
    console.info(
      'getParents',
      allParents.map((node) => node.value),
    );
  };

  const getActiveIndex = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    const indexes = nodes.map((node) => {
      const index = treeRef.current.getIndex(node.value);
      return { value: node.value, index };
    });
    console.info('getIndex', indexes);
  };

  const setActiveChecked = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    nodes.forEach((node) => {
      treeRef.current.setItem(node.value, {
        checked: true,
      });
    });
  };

  const setActiveExpanded = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    nodes.forEach((node) => {
      treeRef.current.setItem(node.value, {
        expanded: true,
      });
    });
  };

  const getPlainData = (item: TreeNodeModel<{ value: string; label?: string }>) => {
    const root = item;
    if (!root) return null;
    const children = (item.getChildren(true) || []) as Array<TreeNodeModel<{ value: string; label?: string }>>;
    const list = [root].concat(children);
    const nodeMap = {};
    const nodeList = list.map((item) => {
      const node = {
        walkData() {
          const data = {
            ...this.data,
          };
          const itemChildren = this.getChildren();
          if (Array.isArray(itemChildren)) {
            data.children = [];
            itemChildren.forEach((childItem) => {
              const childNode = nodeMap[childItem.value];
              const childData = childNode.walkData();
              data.children.push(childData);
            });
          }
          return data;
        },
        ...item,
      };
      nodeMap[item.value] = node;
      return node;
    });
    const [rootNode] = nodeList;
    const data = rootNode.walkData();
    return data;
  };

  const getActivePlainData = () => {
    const nodes = getActivedNodes();
    if (!nodes.length) return;
    const allData = nodes.map((node) => {
      const data = getPlainData(node);
      return { nodeValue: node.value, data };
    });
    console.log('getActivePlainData:', allData);
    return allData;
  };

  return (
    <Space direction="vertical">
      <style>{`.tdesign-tree-operations .t-is-active .t-tree__label { background-color: rgba(0, 0, 255, 0.2);}`}</style>
      <Space direction="vertical">
        <Space>
          <span>严格模式</span>
          <Switch<boolean> value={checkStrictly} onChange={setCheckStrictly} />
        </Space>
        <Space>
          <span>允许多个节点同时高亮</span>
          <Switch<boolean> value={activeMultiple} onChange={setActiveMultiple} />
        </Space>
        <Space>
          <span>插入节点使用高亮节点</span>
          <Switch<boolean> value={useActived} onChange={setUseActived} />
        </Space>
        <Space>
          <span>子节点展开触发父节点展开</span>
          <Switch<boolean> value={expandParent} onChange={setExpandParent} />
        </Space>
      </Space>
      <Space>
        <InputAdornment prepend="filter:">
          <Input value={filterText} onChange={handleInputChange} />
        </InputAdornment>
      </Space>
      <Tree
        ref={treeRef}
        className="tdesign-tree-operations"
        hover
        expandAll
        activable
        checkable
        checkStrictly={checkStrictly}
        line
        allowFoldNodeOnFilter
        data={items}
        actived={activeIds}
        activeMultiple={activeMultiple}
        label={getLabel}
        expandParent={expandParent}
        filter={filterByText}
        operations={renderOperations2}
        onExpand={handleExpand}
        onChange={handleChange}
        onActive={handleActive}
      />
      <Space breakLine>
        <Button theme="primary" onClick={getItem}>
          {"获取 value 为 'node1' 的单个节点"}
        </Button>
        <Button theme="primary" onClick={getAllItems}>
          获取所有节点
        </Button>
        <Button theme="primary" onClick={getActiveChildren}>
          获取高亮节点的所有子节点
        </Button>
        <Button theme="primary" onClick={getAllActived}>
          获取所有高亮节点
        </Button>
        <Button theme="primary" onClick={getActiveChecked}>
          获取高亮节点下的选中节点
        </Button>
        <Button theme="primary" onClick={() => append()}>
          插入一个根节点
        </Button>
        <Button theme="primary" onClick={getActiveParent}>
          获取高亮节点的父节点
        </Button>
        <Button theme="primary" onClick={getActiveParents}>
          获取高亮节点的所有父节点
        </Button>
        <Button theme="primary" onClick={getActiveIndex}>
          获取高亮节点在子节点中的位置
        </Button>
        <Button theme="primary" onClick={setActiveChecked}>
          选中高亮节点
        </Button>
        <Button theme="primary" onClick={setActiveExpanded}>
          展开高亮节点
        </Button>
        <Button theme="primary" onClick={getActivePlainData}>
          获取高亮节点与其子节点的数据
        </Button>
      </Space>
      <Space>
        <strong>* 相关信息通过控制台输出</strong>
      </Space>
    </Space>
  );
};
